1"use client";
2
3import { useParams } from "next/navigation";
4import { useEffect } from "react";
5import { usePage, usePageBlocks } from "@/hooks/use-pages";
6import { usePresence } from "@/hooks/use-presence";
7import { usePageRealtime } from "@/hooks/use-realtime";
8import { useEditorStore } from "@/stores/editor-store";
9import { PageSpinner } from "@/components/editor/page-spinner";
10
11
18export default function PageLayout({ children }: { children: React.ReactNode }) {
19 const params = useParams<{ id: string; block?: string }>();
20 const pageId = params?.id ?? "";
21
22
23 const page = usePage(pageId);
24 usePageBlocks(pageId || "");
25
26 useEffect(() => {
27 useEditorStore.getState().setActivePage(pageId || null);
28 }, [pageId]);
29
30
31 usePageRealtime(pageId || null);
32
33
34
35 usePresence(pageId || null);
36
37
38
39 useEffect(() => {
40 if (params?.block) {
41 useEditorStore.getState().setFocus(params.block);
42 }
43 }, [params?.block, pageId]);
44
45 if (page.isLoading) return <PageSpinner />;
46
47
48
49
50
51 if (page.isError) {
52 const msg = page.error instanceof Error ? page.error.message : "The page could not be loaded.";
53 return (
54 <div className="flex min-h-[50vh] items-center justify-center p-6">
55 <div className="w-full max-w-md rounded-lg border border-border bg-card p-6 text-center shadow-sm">
56 <h2 className="text-base font-semibold">Couldn’t load this page</h2>
57 <p className="mt-1 text-sm text-muted-foreground">{msg}</p>
58 <button
59 type="button"
60 onClick={() => void page.refetch()}
61 className="mt-4 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:opacity-90"
62 >
63 Try again
64 </button>
65 </div>
66 </div>
67 );
68 }
69
70 return <>{children}</>;
71}
72